home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / jcool01.zip / HANDLE.H < prev    next >
C/C++ Source or Header  |  1992-10-01  |  10KB  |  304 lines

  1. //
  2. // Copyright (C) 1992 General Electric Company.
  3. //
  4. // Permission is granted to any individual or institution to use, copy, modify,
  5. // and distribute this software, provided that this complete copyright and
  6. // permission notice is maintained, intact, in all copies and supporting
  7. // documentation.
  8. //
  9. // General Electric Company provides this software "as is" without
  10. // express or implied warranty.
  11. //
  12. // Created: VDN 03/25/92 -- Initial design
  13. // Updated: JAM 08/19/92 -- modernized template syntax, remove macro hacks
  14. // Updated: JAM 08/19/92 -- removed Type##H(andle),P(ointer),R(eference)
  15. //                          typedefs -- not possible with modern templates
  16. //
  17. // Handle<Type> works with Shared mixin on the object to provide 
  18. // a very simple scheme of memory management with reference count.
  19. // Handles to objects are stored in containers or other data structures,
  20. // instead of pointers to objects, if these objects are shared.
  21. // If your design of the object hierarchy has layers, from the root O1
  22. // to the leaves On, parent node Oi should store Oj, or a handle to Oj,
  23. // for automatic deletion of all the nodes in the tree when
  24. // the root O1 is deleted. In essence, you design an acyclic graph
  25. // for your hierarchy. Nodes can be shared with reference count.
  26. // Backward pointers that create cycles in your network should be broken
  27. // up by storing pointers instead of handles. Note that pointers stored in 
  28. // COOL containers are not deleted, while objects are.
  29. //
  30. // Be aware: Empty handles, just as NULL pointers, can create segmentation 
  31. // faults.
  32. //
  33. // Reference:
  34. // 1. Stroupstrup(1991) C++ programming language, 2nd ed, section 13.9.
  35. // 2. Coplien(1992) Advanced C++ programming techniques and idioms.
  36.  
  37.  
  38. #ifndef HANDLEH
  39. #define HANDLEH
  40.  
  41. #ifndef MISCH
  42. #include <misc.h>                // for Boolean
  43. #endif
  44.  
  45. #ifndef SHAREDH
  46. #include <cool/Shared.h>
  47. #endif
  48.  
  49. template <class Type> 
  50. class CoolHandle {
  51. public:
  52.   /*inline##*/ CoolHandle();            // Empty constructor
  53.   /*inline##*/ CoolHandle(Type* optr);        // construct hdl from ptr
  54.   /*inline##*/ CoolHandle(Type& obj);        // construct hdl from obj
  55.   /*inline##*/ CoolHandle(const CoolHandle<Type>& h); // copy constructor
  56.   
  57.   /*inline##*/ ~CoolHandle();            // destructor
  58.   
  59.   /*inline##*/ Type* operator-> ();            // dereference
  60.   
  61.   /*inline##*/ CoolHandle<Type>& operator= (Type* optr); // assign to another ptr
  62.   /*inline##*/ CoolHandle<Type>& operator= (Type& obj);  // assign to obj reference
  63.   /*inline##*/ CoolHandle<Type>& operator= (const CoolHandle<Type>& h); // to hdl
  64.   
  65. //##  /*inline##*/ friend Type* ptr (CoolHandle<Type>&);    // convert to ptr
  66. //##  /*inline##*/ friend Type& ref (CoolHandle<Type>&);    // convert to reference
  67. //##  /*inline##*/ friend CoolHandle<Type> hdl (Type* optr=NULL); // convert to hdl
  68.   
  69.   /*inline##*/ operator Type*();            // automatic conversion to ptr
  70.   /*inline##*/ operator Type&();            // automatic conversion to ref
  71.  
  72. #define DECLARE_HANDLE_OPERATOR(op)                          \
  73.   /*inline##*/ friend Boolean operator op (const CoolHandle<Type>&,               \
  74.                      const CoolHandle<Type>&);
  75. //##  DECLARE_HANDLE_OPERATOR(==)
  76. //##  DECLARE_HANDLE_OPERATOR(!=)
  77. //##  DECLARE_HANDLE_OPERATOR(<=)
  78. #undef DECLARE_HANDLE_OPERATOR
  79.  
  80. //##  /*inline##*/ friend ostream& operator<< (ostream&, const CoolHandle<Type>&);
  81. //##  /*inline##*/ friend ostream& operator<< (ostream&, const CoolHandle<Type>*);
  82.  
  83. //##private:  BC++ 3.1 doesn't like those friend functions declared in class
  84. public:
  85.   Type* rep;                    // pointer to shared obj
  86.  
  87.   /*inline##*/ void null_pointer_error (const char* fcn, const char* type);
  88. };
  89.  
  90. // Handle() -- Empty constructor
  91. // Input:             ptr
  92. // Output:            None
  93.  
  94. template<class Type>
  95. inline CoolHandle<Type>::CoolHandle()
  96. : rep(NULL) {}                    // pointer is NULL
  97.  
  98. // Handle() -- Default constructor from a pointer to object, inc count.
  99. // Input:             ptr
  100. // Output:            None
  101.  
  102. template<class Type>
  103. inline CoolHandle<Type>::CoolHandle(Type* optr) 
  104. : rep(optr) {
  105.   CoolShared::reference(this->rep);        // inc count on shared obj
  106. }
  107.  
  108. // Handle() -- Constructor from an object, inc count.
  109. // Input:             reference
  110. // Output:            None
  111.  
  112. template<class Type>
  113. inline CoolHandle<Type>::CoolHandle(Type& obj) 
  114. : rep(&obj) {
  115.   obj.reference();                // inc count on shared obj
  116. }
  117.  
  118. // Handle (handle&) -- Copy constructor from another handle
  119. // Input:             handle to be copied
  120. // Output:            None
  121.  
  122. template<class Type>
  123. inline CoolHandle<Type>::CoolHandle(const CoolHandle<Type>& h) 
  124. : rep(h.rep) {
  125.   CoolShared::reference(this->rep);        // inc count on shared obj
  126. }
  127.  
  128. // ~Handle  -- Destructor for Handle class, dec count and free object.
  129. // Input:              None
  130. // Output:             None
  131.  
  132. template<class Type>
  133. inline CoolHandle<Type>::~CoolHandle() {
  134.   if (CoolShared::dereference(this->rep) == 0)    
  135.     delete rep;                    // dec count on obj & delete
  136. }
  137.  
  138. // operator-> -- Dereference overloaded, to make handle look like pointer.
  139. // Input:              None
  140. // Output:             pointer to object.
  141.  
  142. template<class Type>
  143. inline Type* CoolHandle<Type>::operator->() {
  144.   return this->rep;                
  145. }
  146.  
  147.  
  148. // operator= -- Assignment to another pointer, check for aliasing.
  149. // Input:              pointer to object
  150. // Output:             handle on lhs of =
  151.  
  152. template<class Type>
  153. inline CoolHandle<Type>& CoolHandle<Type>::operator=(Type* optr) {
  154.   if (this->rep != optr) {            // aliasing -> premature delete
  155.     if (CoolShared::dereference(this->rep)==0)
  156.       delete this->rep;                // dec count on old obj & delete
  157.     this->rep = optr;
  158.     CoolShared::reference(this->rep);        // inc count on shared obj
  159.   }
  160.   return *this;
  161. }
  162.  
  163.  
  164. // operator=(Type&) -- Assignment to another object reference
  165. // Input:              reference to object
  166. // Output:             handle on lhs of =
  167.  
  168. template<class Type>
  169. inline CoolHandle<Type>& CoolHandle<Type>::operator=(Type& obj) {
  170.   if (this->rep != &obj) {            // aliasing cause premature delete
  171.     if (CoolShared::dereference(this->rep) == 0)
  172.       delete this->rep;                // dec count on old obj & delete
  173.     this->rep = &obj;
  174.     obj.reference();                // inc count on shared obj
  175.   }
  176.   return *this;
  177. }
  178.  
  179. // operator= -- Assignment to another handle
  180. // Input:              handle on rhs of =
  181. // Output:             handle on lhs of =
  182.  
  183. template<class Type>
  184. inline CoolHandle<Type>& CoolHandle<Type>::operator=(const CoolHandle<Type>& h) {
  185.   if (this->rep != h.rep) {            // aliasing cause premature delete
  186.     if (CoolShared::dereference(this->rep) == 0)
  187.       delete this->rep;                // dec count on old obj & delete
  188.     this->rep = h.rep;
  189.     CoolShared::reference(this->rep);        // inc count on shared obj
  190.   }
  191.   return *this;
  192. }
  193.  
  194. // ptr  -- Manual conversion to pointer
  195. // Input:              handle to object
  196. // Output:             pointer to object
  197.  
  198. template<class Type>
  199. inline Type* ptr (CoolHandle<Type>& h) {
  200.   return h.rep;
  201. }
  202.  
  203. // ref  -- Manual conversion to reference
  204. // Input:              handle to object
  205. // Output:             ref to object
  206.  
  207. template<class Type>
  208. inline Type& ref (CoolHandle<Type>& h) {
  209. #if ERROR_CHECKING
  210.     if (!h.rep)
  211.       h.null_pointer_error("ref", "Type");
  212. #endif
  213.   return *(h.rep);
  214. }
  215.  
  216. // Handle hdl (Type*) -- Manual conversion to handle, returned by value.
  217. //                     A temporary handle is created and deleted by compiler.
  218. // Input:              pointer to object
  219. // Output:             handle to object
  220.  
  221. template<class Type>
  222. inline CoolHandle<Type> hdl(Type* optr) {
  223.   CoolHandle<Type> h(optr);            // handle with given optr
  224.   return h;                    // copy on return by value
  225. }
  226.  
  227. // operator Type*  -- Automatic conversion to pointer
  228. //                     Be careful not to store and delete ptrs outside of handles.
  229. // Input:              handle to object
  230. // Output:             pointer to object
  231.  
  232. template<class Type> 
  233. inline CoolHandle<Type>::operator Type* () {
  234.   return this->rep;
  235. }
  236.  
  237.  
  238. // operator Type&  -- Automatic conversion to reference
  239. // Input:              handle to object
  240. // Output:             reference to object
  241.  
  242. template<class Type> 
  243. inline CoolHandle<Type>::operator Type& () {
  244. #if ERROR_CHECKING
  245.     if (!this->rep)
  246.       this->null_pointer_error("operator Type&", #Type);
  247. #endif
  248.   return *(this->rep);
  249. }
  250.  
  251. // Operator== -- Overload comparison operators for handles. Compare pointers.
  252. // Input:             handles 
  253. // Ouput:             Boolean
  254.  
  255. #define IMPLEMENT_HANDLE_OPERATOR(op)                          \
  256. template<class Type>                          \
  257. inline Boolean operator op (const CoolHandle<Type>& h1,               \
  258.                 const CoolHandle<Type>& h2) {              \
  259.   return h1.rep op h2.rep;                              \
  260. }
  261.  
  262. IMPLEMENT_HANDLE_OPERATOR(==)
  263. IMPLEMENT_HANDLE_OPERATOR(!=)
  264. IMPLEMENT_HANDLE_OPERATOR(<=)
  265.  
  266.  
  267. #undef IMPLEMENT_HANDLE_OPERATOR
  268.   
  269.  
  270. // operator<< -- print handle object to ostream.
  271. // Input:              ostream and handle to object
  272. // Output:             ostream
  273.  
  274. template<class Type>
  275. inline ostream& operator<< (ostream& os, const CoolHandle<Type>& h) {
  276.   Type* r = h.rep;
  277.   if (r) 
  278.     return os << *r;
  279.   else
  280.     return os << "Empty";
  281. }
  282.  
  283.  
  284. // operator<< -- print pointer to a handle to ostream.
  285. // Input:              ostream and pointer to handle 
  286. // Output:             ostream
  287.  
  288. template<class Type>
  289. inline ostream& operator<< (ostream& os, const CoolHandle<Type>* h) {
  290.   return os << *h;
  291. }
  292.  
  293. template<class Type>
  294. inline void CoolHandle<Type>::null_pointer_error (const char* fcn, 
  295.                           const char* type) {
  296.   //RAISE (Error, SYM(CoolHandle), SYM(NullPointer))
  297.   printf ("CoolHandle<%s>::%s: Pointer inside handle is NULL.\n",
  298.       type, fcn);
  299.   abort ();
  300. }
  301.  
  302. #endif                        // HANDLEH
  303.  
  304.